#include <rtthread.h>
#ifdef WIOTA_API_TEST
#include "uc_wiota_api.h"

#define FREQ_IDX (145)
#define HOPPING FREQ_IDX(147)
#define ACT_TIME 3
#define AP_MAX_POW 30 // actually 10 TODO:

void drop_func(unsigned int user_id)
{
    rt_kprintf("user_id 0x%x dropped\n", user_id);
}

void recv_data_func(unsigned int user_id, unsigned char *recv_data, unsigned int data_len, unsigned char type)
{
    rt_kprintf("recved ul data, user_id 0x%x, type %d, data_len %d:\n", user_id, type, data_len);
    for (int index = 0; index < data_len; index++)
    {
        if ((index != 0) && (index % 16 == 0))
        {
            rt_kprintf("\n");
        }
        rt_kprintf("0x%x ", *recv_data++);
    }
    rt_kprintf("\n");
}

// wiota run process
void wiota_run_process(void)
{
    sub_system_config_t config = {0};

    // wiota init
    uc_wiota_init();
    rt_kprintf("uc_wiota_init suc\n");

    // set freq
    uc_wiota_set_freq_info(145);
    rt_kprintf("uc_wiota_set_freq_info suc %d\n", uc_wiota_get_freq_info());

    // get config first
    uc_wiota_get_system_config(&config);
    rt_kprintf("uc_wiota_get_system_config suc, power %d, id_len %d, pp %d, symbol_length %d, dlul_ratio %d, bt_value %d, group_number %d, spectrum_idx %d, old_subsys_v %d, bitscb %d, subsystem_id 0x%x\n",
               config.power,
               config.id_len,
               config.pp,
               config.symbol_length,
               config.dlul_ratio,
               config.bt_value,
               config.group_number,
               config.spectrum_idx,
               config.old_subsys_v,
               config.bitscb,
               config.subsystem_id);

    config.power = 20; // TODO:

    // set config
    uc_wiota_set_system_config(&config);
    rt_kprintf("uc_wiota_set_system_config suc\n");

    // set act time after set system config
    uc_wiota_set_active_time(ACT_TIME);
    rt_kprintf("uc_wiota_set_active_time suc %d\n", uc_wiota_get_active_time());

    // wiota start
    uc_wiota_run();
    rt_kprintf("uc_wiota_run suc\n");
}

// wiota exit and restart
void wiota_exit_and_restart(void)
{
    uc_wiota_exit();
    rt_kprintf("uc_wiota_exit suc\n");

    rt_thread_mdelay(2000);

    wiota_run_process();
}

// scan freq test
void scan_freq_test(void)
{
    unsigned char freq_array[20] = {5, 15, 25, 35, 45, 55, 65, 75, 85, 95, 105, 115, 125, 135, 145, 155, 165, 175, 185, 195};
    signed int timeout = 60000;
    uc_scan_recv_t scan_info = {0};
    unsigned char freq_num = sizeof(freq_array) / sizeof(unsigned char);

    uc_wiota_scan_freq(freq_array, freq_num, 0, timeout, &scan_info);
    // uc_wiota_scan_freq(RT_NULL, 0, 0, -1, &scan_info); // if freq_array == NULL && freq_num == 0, default scan all,about 3 min
    if (scan_info.result == UC_OP_SUCC)
    {
        uc_scan_freq_t *freq_list = scan_info.freq_info;
        for (unsigned char idx = 0; idx < scan_info.freq_num; idx++)
        {
            rt_kprintf("freq_idx = %u, snr = %d, rssi = %d, is_synced = %d\n", freq_list[idx].freq_idx, freq_list[idx].snr, freq_list[idx].rssi, freq_list[idx].is_synced);
        }
    }
    else
    {
        rt_kprintf("scan freq failed or timeout\n");
    }

    if (scan_info.freq_info != RT_NULL)
    {
        rt_free(scan_info.freq_info); // !!!need be manually released after use
        scan_info.freq_info = RT_NULL;
    }

    rt_thread_mdelay(2000);
    // restart wiota ps after scan freq
    // wiota_exit_and_restart();
}

// hopping freq test
void hopping_freq_test(void)
{
    uc_wiota_set_hopping_freq(FREQ_IDX);
    uc_wiota_set_hopping_mode(20, 30); // after working for 20 frames at original freq_point, skip to the freq hopping freq_point and work for 30 frames
}

void send_dl_callback(void *para, uc_send_recv_t *result)
{
    unsigned int *data_id = (unsigned int *)para;

    rt_kprintf("0x%x data_id %d send dl result %d\n", result->user_id, data_id[0], result->result);
}

// send dl test
void send_dl_test(int is_block)
{
    signed int timeout = 100000; // ms
    unsigned char dl_data[310] = {0};
    static int data_id[1] = {0};
    int dl_data_len = 310;
    int result = 0;

    for (int i = 0; i < 310; i++)
    {
        dl_data[i] = 'd';
    }

    unsigned int user_id = 0x63c8654c; // curr_node->user_id;

    rt_kprintf("user_id 0x%x\n", user_id);

    if (is_block)
    {
        result = uc_wiota_send_data(dl_data, dl_data_len, user_id, timeout, RT_NULL, data_id);
        data_id[0]++;
        rt_kprintf("0x%x data_id %d send dl result %d\n", user_id, data_id[0], result);
    }
    else
    {
        for (int i = 0; i < 30; i++)
        {
            uc_wiota_send_data(dl_data, dl_data_len, user_id, timeout, send_dl_callback, data_id);
            data_id[0]++;
        }
    }
}

void send_bc_callback(void *para, uc_send_recv_t *result)
{
    unsigned int *data_id = (unsigned int *)para;

    rt_kprintf("data_id %d send bc result %d\n", data_id[0], result->result);
}

// send bc test
void send_bc_test(int is_block)
{
    signed int timeout = 100000; // ms
    static int bc_data_id[1] = {0};
    static int ota_data_id[1] = {0};
    static unsigned char bc_data[1024] = {0};
    static unsigned char ota_data[1024] = {0};
    int result = 0;
    int data_len = 1024;
    for (int i = 0; i < 1024; i++)
    {
        bc_data[i] = 'a';
        ota_data[i] = 'b';
    }
    uc_wiota_set_broadcast_mcs(UC_MCS_LEVEL_4);

    if (is_block)
    {
        result = uc_wiota_send_broadcast_data(bc_data, data_len, NORMAL_BROADCAST, timeout, RT_NULL, bc_data_id);
        rt_kprintf("send bc block %d-%d\n", bc_data_id[0], result);
    }
    else
    {
        uc_wiota_send_broadcast_data(bc_data, data_len, NORMAL_BROADCAST, timeout, send_bc_callback, bc_data_id);
    }
    bc_data_id[0]++;

    for (int i = 0; i < 30; i++)
    {
        if (is_block)
        {
            result = uc_wiota_send_broadcast_data(ota_data, data_len, OTA_BROADCAST, timeout, RT_NULL, ota_data_id);
            rt_kprintf("send ota block %d-%d\n", ota_data_id[0], result);
        }
        else
        {
            uc_wiota_send_broadcast_data(ota_data, data_len, OTA_BROADCAST, timeout, send_bc_callback, ota_data_id);
        }
        ota_data_id[0]++;
    }
}

// read temp test
void read_temp_test(void)
{
    uc_temp_recv_t read_temp = {0};
    unsigned short timeout = 10000;

    if (UC_OP_SUCC == uc_wiota_read_temperature(&read_temp, timeout))
    {
        rt_kprintf("read_temp %d\n", read_temp.temp);
    }
    else
    {
        rt_kprintf("read temp failed\n");
    }
}

// get version test
void get_version_test()
{
    char wiota_version_8088[15] = {0};
    char git_info_8088[36] = {0};
    char make_time_8088[36] = {0};
    char wiota_version_8288[15] = {0};
    char git_info_8288[36] = {0};
    char make_time_8288[36] = {0};
    int cce_version = 0;

    uc_wiota_get_version(wiota_version_8088, git_info_8088, make_time_8088, wiota_version_8288, git_info_8288, make_time_8288, &cce_version);
    rt_kprintf("wiota lib version: %s,%s\n", wiota_version_8088, wiota_version_8288);
    rt_kprintf("wiota lib git info: %s,%s\n", git_info_8088, git_info_8288);
    rt_kprintf("wiota lib make time: %s,%s\n", make_time_8088, make_time_8288);
    rt_kprintf("cce version: %x\n", cce_version);
}

// test! add iote to blacklist
void blacklist_test(void)
{
    unsigned int add_array[5] = {0x4c00ccdb, 0xfb3eae00, 0x38f8c8d8, 0x8aff8783, 0x33139955};
    unsigned int remove_array[2] = {0x4c00ccdb, 0x8aff8783};
    unsigned short add_num = sizeof(add_array) / sizeof(unsigned int);
    unsigned short remove_num = sizeof(remove_array) / sizeof(unsigned int);
    uc_blacklist_t *g_blacklist = RT_NULL;
    unsigned short bl_num = 0;

    // add id to bl
    uc_wiota_add_iote_to_blacklist(add_array, add_num);

    // remove id from bl
    uc_wiota_remove_iote_from_blacklist(remove_array, remove_num);

    // printf bl
    g_blacklist = uc_wiota_get_blacklist(&bl_num);

    uc_blacklist_t *curr_node;

    rt_kprintf("bl_num %d\n", bl_num);

    rt_slist_for_each_entry(curr_node, &g_blacklist->node, node)
    {
        rt_kprintf("bl_id:0x%x\n", curr_node->user_id);
    }

    uc_wiota_linklist_deinit(LIST_TYPE_BL);
}

void query_dev_pos_test(void)
{
    // unsigned int user_id[5] = {0x4c00ccdb, 0xfb3eae00, 0x38f8c8d8, 0x8aff8783, 0x33139955};
    static unsigned int user_id[200] = {0};
    uc_dev_pos_t *dev_pos = RT_NULL;

    unsigned int offset = 0x0;
    for (int idx = 0; idx < 200; idx++)
    {
        user_id[idx] = 0x80000064 + offset;
        offset += 0x1;
    }
    rt_kprintf("query begin\n");
    dev_pos = uc_wiota_query_dev_pos_by_userid(user_id, 200);
    if (dev_pos)
    {
        for (int i = 0; i < 200; i++)
        {
            rt_kprintf("0x%x,%d-%d-%d\n", user_id[i], dev_pos[i].group_idx, dev_pos[i].burst_idx, dev_pos[i].slot_idx);
        }
        rt_free(dev_pos);
    }
    else
    {
        rt_kprintf("query pos fail or timeout\n");
    }
}

// freq_list test
void freq_list_test(void)
{
    unsigned char set_freq_list[16] = {5, 15, 25, 35, 45, 55, 65, 75, 85, 95, 105, 115, 125, 135, 145, 155};
    unsigned int set_freq_num = sizeof(set_freq_list) / sizeof(unsigned char);
    unsigned char get_freq_list[16] = {0};
    unsigned int get_freq_num = 0;

    uc_wiota_set_freq_list(set_freq_list, set_freq_num);
    rt_thread_mdelay(2000);
    uc_wiota_get_freq_list(get_freq_list, &get_freq_num);

    rt_kprintf("get_freq_num %d\n", get_freq_num);
    for (int i = 0; i < get_freq_num; i++)
    {
        rt_kprintf("get_freq_list %d\n", get_freq_list[i]);
    }
}

void wiota_api_test_task(void *para)
{
    if (RT_EOK != uc_wiota_at_client_init())
    {
        rt_kprintf("uc_wiota_at_client_init fail\n");
        return;
    }
    rt_kprintf("uc_wiota_at_client_init suc\n");

    while (uc_wiota_at_client_connect(5000) != RT_EOK)
    {
        rt_thread_mdelay(1000);
    }
    rt_kprintf("wiota at client connect ok\n");

    wiota_run_process();

    // scan freq
    scan_freq_test();

    // hopping freq
    hopping_freq_test();

    // reg cb
    uc_wiota_register_iote_dropped_callback(drop_func);
    uc_wiota_register_recv_data_callback(recv_data_func);

    // bl test
    blacklist_test();

    // ap max power set
    uc_wiota_set_ap_tx_power(AP_MAX_POW);

    // get version test
    get_version_test();

    // read temp test
    // read_temp_test();

    // query dev pos test
    query_dev_pos_test();

    // freq_list test
    //  freq_list_test();

    // send bc test
    send_bc_test(0);
    send_bc_test(1);

    while (1)
    {
        // send dl test
        send_dl_test(0);
        send_dl_test(1);

        // ap state info query
        // state_info_query_test();

        rt_thread_mdelay(10000);
    }

    return;
}

void wiota_api_test(void)
{
    rt_thread_t test_handler = rt_thread_create("api_test", wiota_api_test_task, RT_NULL, 1024, 3, 3);
    if (test_handler != RT_NULL)
    {
        rt_thread_startup(test_handler);
    }
}
#endif // WIOTA_API_TEST
